/*
 * Copyright (c) 2020-2021, SERI Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2022-05-22     Lyons        first version
 */

module pa_fpu_data_judge (
    single_i,
    double_i,
    src_i,
    rst_type_o
    );

`include "pa_fpu_param.v"

input                           single_i;
input                           double_i;
input                           src_i;
output                          rst_type_o;

wire                            single_i;
wire                            double_i;
wire [`FLOAT_WIDTH-1:0]         src_i;
wire [`TYPE_WIDTH-1:0]          rst_type_o;


wire                            src_e_all1;
wire                            src_e_all0;
wire                            src_f_all1;
wire                            src_f_all0;

wire                            src_is_cnan;
wire                            src_is_qnan;
wire                            src_is_snan;
wire                            src_is_inf;
wire                            src_is_normal;
wire                            src_is_subnormal;
wire                            src_is_zero;
wire                            src_is_e_max;
wire                            src_is_e_zero;
wire                            src_is_f_max;
wire                            src_is_f_zero;

wire [`DOUBLE_EXPN_WIDTH-1:0]   src_expn;
wire [`DOUBLE_FRAC_WIDTH-1:0]   src_frac;


assign src_expn[`DOUBLE_EXPN_WIDTH-1:0] = {{`DOUBLE_FRAC_WIDTH}{single_i}} & {3'b0,  src_i[`SINGLE_WIDTH-2:`SINGLE_FRAC_WIDTH]}
                                        | {{`DOUBLE_FRAC_WIDTH}{double_i}} & {src_i[`DOUBLE_WIDTH-2:`DOUBLE_FRAC_WIDTH]};

assign src_frac[`DOUBLE_FRAC_WIDTH-1:0] = {{`DOUBLE_FRAC_WIDTH}{single_i}} & {29'b0, src_i[`SINGLE_FRAC_WIDTH-1:0]}
                                        | {{`DOUBLE_FRAC_WIDTH}{double_i}} & {src_i[`DOUBLE_FRAC_WIDTH-1:0]};

assign src_e_all1 = single_i & ((&src_expn[`SINGLE_EXPN_WIDTH-1:0]) == 1)
                  | double_i & ((&src_expn[`DOUBLE_EXPN_WIDTH-1:0]) == 1);
assign src_e_all0 = (|src_expn[`DOUBLE_EXPN_WIDTH-1:0]) == 0;

assign src_f_all1 = single_i & ((&src_frac[`SINGLE_FRAC_WIDTH-1:0]) == 1)
                  | double_i & ((&src_frac[`DOUBLE_FRAC_WIDTH-1:0]) == 1);
assign src_f_all0 = (|src_frac[`DOUBLE_FRAC_WIDTH-1:0]) == 0;

assign src_is_f_zero = src_f_all0;
assign src_is_f_max  = src_f_all1;

assign src_is_e_zero = src_e_all0;
assign src_is_e_max  = src_e_all1;

assign src_is_cnan = single_i & ~(&src_i[63:32])
                   | double_i & 1'b0;

assign src_is_snan = src_is_e_max
                  && ~src_is_f_zero
                  && ~( single_i & src_frac[`SINGLE_FRAC_WIDTH-1]
                      | double_i & src_frac[`DOUBLE_FRAC_WIDTH-1] );

assign src_is_qnan = src_is_e_max
                  && ~src_is_f_zero
                  && ( single_i & src_frac[`SINGLE_FRAC_WIDTH-1]
                     | double_i & src_frac[`DOUBLE_FRAC_WIDTH-1] );

assign src_is_inf = src_is_e_max && src_is_f_zero;

assign src_is_subnormal = src_is_e_zero && ~src_f_all0;

assign src_is_zero = src_is_e_zero && src_is_f_zero;

assign src_is_normal = ~src_is_zero && ~src_is_inf && ~src_is_snan && ~src_is_qnan && ~src_is_cnan;

assign rst_type_o[`TYPE_WIDTH-1:0] = {
    src_is_cnan,
    (src_is_qnan | src_is_cnan),
    src_is_snan,
    src_is_inf,
    (src_is_normal | src_is_subnormal),
    src_is_subnormal,
    src_is_zero
    };

endmodule